package com.thirdnf.wigets;

import org.jetbrains.annotations.NotNull;

import java.awt.event.ActionEvent;
import java.net.URL;
import java.util.*;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;

/**
 * This is a simple 25 x 25 button which holds an image and acts like a button.  This is based off a JLabel
 * rather than a JButton so that it is not affected by the Look and Feel.  Specifically the L&F for MacOS
 * makes all buttons very wide which is sometimes not what you want.
 * <p/>
 * This seems like a really basic type of a button but despite my best efforts I can't seem to find one
 * available on-line.
 *
 * @author Joshua Gerth - jgerth@thirdnf.com
 */
public class ImageButton extends JPanel
{
    // Our internal label which holds the button
    private final JLabel _label = new JLabel();

    // We have only one height and width, regardless of the L&F
    private static int height = 25;
    private static int width = 25;

    // List of things that care if we get clicked
    private final List<ActionListener> _actionListeners = new ArrayList<ActionListener>();

    // Our borders so we can respond to mouse over.
    private final Border OverBorder = BorderFactory.createLineBorder(Color.black);
    private final Border OutBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1);

    private final Color _backgroundColor;

    private boolean _enabled = true;

    /**
     * Empty constructor so this can be used as a bean.
     */
    public ImageButton()
    {
        setLayout(new BorderLayout());
        add(_label);

        _label.setHorizontalAlignment(JLabel.CENTER);
        _label.setVerticalAlignment(JLabel.CENTER);
        _backgroundColor = _label.getBackground();

        Dimension d = new Dimension(width, height);
        setSize(d);
        setMaximumSize(d);
        setMinimumSize(d);
        setPreferredSize(d);

        URL noIcon = getClass().getResource("noIcon.png");

        if (noIcon != null) { setImageIcon(new ImageIcon(noIcon)); }

        addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                handleMouseClicked();
            }

            @Override
            public void mousePressed(MouseEvent e) {
                handleMousePressed();
                //To change body of implemented methods use File | Settings | File Templates.
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                handleMouseReleased();
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                handleMouseEntered();
            }

            @Override
            public void mouseExited(MouseEvent e) {
                handleMouseExit();
            }
        });
    }


    /**
     * Set the image which is going to be shown.
     *
     * @param icon (not null) The image to show
     */
    public void setImageIcon(@NotNull Icon icon)
    {
        _label.setIcon(icon);
    }


    @Override
    public void setEnabled(boolean enabled)
    {
        _enabled = enabled;
        _label.setEnabled(enabled);
    }


    public void addActionListener(@NotNull ActionListener actionListener)
    {
        _actionListeners.add(actionListener);
    }


    private void handleMouseClicked()
    {
        if (! _enabled) { return; }

        ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "click");

        // Okay, let everyone know we have been clicked
        for (ActionListener actionListener : _actionListeners) {
            actionListener.actionPerformed(event);
        }
    }


    private void handleMousePressed()
    {
        if (! _enabled) { return; }
        setBackground(Color.darkGray);
    }

    private void handleMouseReleased()
    {
        setBackground(_backgroundColor);
    }

    private void handleMouseEntered()
    {
        if (! _enabled) { return; }

        setOpaque(true);
        setBorder(OverBorder);
    }

    private void handleMouseExit()
    {
        setOpaque(false);
        setBorder(OutBorder);
    }
}

